/* -*- coding: utf-8 -*- */
/*  -*- c++ -*- */

%{
#include <cstdlib>
#include <cerrno>
#include <climits>
#include <string>
#include <scanner.h>
#include <map>

  /* Importamos los tokens del parser */
  typedef netthumb::Parser::token token;
  typedef netthumb::Parser::token_type token_type;

// #include <DriverParser.hh>
// #include <parser.tab.h>


#define yyterminate() return token::END
%}

%option c++
%option prefix="Netthumb"
%option batch
%option debug
%option stack
%option noyywrap nounput

TAB               \t
FINLINEA          \r|\n|\r\n|\n\r
BLANCO            [ \t]
ELIMINABLE        ({TAB}|{BLANCO})+

INICIO_COMENTARIO "/*"
FIN_COMENTARIO    "*/"
COMENTARIO        "//"[^\n]*
INICIO_BLOQUE     "{"
FIN_BLOQUE        "}"
DOSPUNTOS         ":"
IP_ADDR           [0-9]{1,3}"."[0-9]{1,3}"."[0-9]{1,3}"."[0-9]{1,3}"/"[0-9]{1,2}
VINT              [[:digit:]]+
ID                \\?[[:alpha:]_][[:alnum:]_]*
%x COMENTARIO

%{
#define YY_USER_ACTION yylloc->columns(yyleng);
%}

%% /* Expresiones regulares */

%{
  yylloc->step();
%}

{BLANCO}+   yylloc->step();
{FINLINEA}+   yylloc->lines(yyleng); yylloc->step();

{VINT}              {yylval->sval = new std::string(YYText()); return token::VINT;}
{INICIO_BLOQUE}     {return token::INICIO_BLOQUE;}
{FIN_BLOQUE}        {return token::FIN_BLOQUE;}

{DOSPUNTOS}         {return token::DOSPUNTOS;}
{ID}                {
                     yylval->sval = new std::string(YYText());
                     return checkKeyword(YYText());
                    }
{IP_ADDR}           {
                     yylval->sval = new std::string(YYText());
                     return token::IP_ADDR;
                    }
{COMENTARIO}        {/*Bye, comments!*/}
{INICIO_COMENTARIO} {BEGIN(COMENTARIO);}

<COMENTARIO>[^*\n]*
<COMENTARIO>"*"+[^*/]*
<COMENTARIO>"*"+"/"        BEGIN(INITIAL);

.                   {}


%% /* Codigo adicional */

namespace netthumb {

  Scanner::Scanner(std::istream* in,
		   std::ostream* out)
    : NetthumbFlexLexer(in,out)
{
  initScanner();
}

  Scanner::~Scanner(){}

void
Scanner::set_debug(bool b)
{
  yy_flex_debug=b;
}

void
Scanner::initScanner()
{
    reservadas["host"]        =   token::NETTHUMB_HOST;
    reservadas["dev"]         =   token::NETTHUMB_DEV;
    reservadas["link"]        =   token::NETTHUMB_LINK;
    reservadas["up"]          =   token::NETTHUMB_UP;
    reservadas["down"]        =   token::NETTHUMB_DOWN;
    reservadas["addr"]        =   token::NETTHUMB_ADDR;
    reservadas["network"]     =   token::NETTHUMB_NETWORK;
    reservadas["scope"]       =   token::NETTHUMB_SCOPE;
    reservadas["global"]      =   token::NETTHUMB_GLOBAL;
    reservadas["site"]        =   token::NETTHUMB_SITE;
    reservadas["route"]       =   token::NETTHUMB_ROUTE;
    reservadas["net"]         =   token::NETTHUMB_NET;
    reservadas["default"]     =   token::NETTHUMB_DEFAULT;
    reservadas["via"]         =   token::NETTHUMB_VIA;
    reservadas["metric"]      =   token::NETTHUMB_METRIC;
    reservadas["priority"]    =   token::NETTHUMB_PRIORITY;
    reservadas["unicast"]     =   token::NETTHUMB_UNICAST;
    reservadas["unreachable"] =   token::NETTHUMB_UNREACHABLE;
    reservadas["blackhole"]   =   token::NETTHUMB_BLACKHOLE;
    reservadas["prohibit"]    =   token::NETTHUMB_PROHIBIT;
    reservadas["local"]       =   token::NETTHUMB_LOCAL;
    reservadas["broadcast"]   =   token::NETTHUMB_BROADCAST;
    reservadas["throw"]       =   token::NETTHUMB_THROW;
    reservadas["nat"]         =   token::NETTHUMB_NAT;
    reservadas["anycast"]     =   token::NETTHUMB_ANYCAST;
    reservadas["multicast"]   =   token::NETTHUMB_MULTICAST;
    reservadas["router"]      =   token::NETTHUMB_ROUTER;
    reservadas["type"]        =   token::NETTHUMB_TYPE;
    reservadas["mtu"]         =   token::NETTHUMB_MTU;
    reservadas["on"]          =   token::NETTHUMB_ON;
    reservadas["off"]         =   token::NETTHUMB_OFF;
}

token_type
Scanner::checkKeyword(std::string id)
{
  std::map<std::string,token_type>::const_iterator pos = reservadas.find(id);
  if(pos != reservadas.end())
    {
      return pos->second;
    }
  return token::ID;
}

}

/* This implementation of ExampleFlexLexer::yylex() is required to fill the
 * vtable of the class ExampleFlexLexer. We define the scanner's main yylex
 * function via YY_DECL to reside in the Scanner class instead. */

#ifdef yylex
#undef yylex
#endif

int NetthumbFlexLexer::yylex()
{
    std::cerr << "in NetthumbFlexLexer::yylex() !" << std::endl;
    return 0;
}

/* When the scanner receives an end-of-file indication from YY_INPUT, it then
 * checks the yywrap() function. If yywrap() returns false (zero), then it is
 * assumed that the function has gone ahead and set up `yyin' to point to
 * another input file, and scanning continues. If it returns true (non-zero),
 * then the scanner terminates, returning 0 to its caller. */

// int NetthumbFlexLexer::yywrap()
// {
//   return 1;
// }

/*
DriverParser::scan_begin ()
{
    yy_flex_debug = trace_scanning;
    if (file == "-")
        yyin = stdin;
    else if (!(yyin = fopen (file.c_str (), "r"))) {
        error (std::string ("cannot open ") + file);
        exit (1);
    }
}

void
DriverParser::scan_end ()
{
    fclose (yyin);
}
*/
